#include "Main.h"
#include "Utils.h"
#include "Scripting.h"

#ifndef _MIRC_DLL
#define _MIRC_DLL(x) extern "C" int WINAPI x( HWND mWnd, HWND aWnd, char* data, char*, BOOL, BOOL )
#endif

HANDLE hFileMap = NULL;
LPSTR mData;
HWND _mWnd, _aWnd;

_MIRC_DLL( LoadScript )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	if ( szData )
	{
		FILE* pFile = fopen( szData, "r" );

		if ( pFile ) 
		{
			CSquirrel* pScript = CSquirrelManager::New( szData );

			fclose( pFile );

			strcpy( data, "1" );
			return 3;
		}
	}

	return 3;
}

_MIRC_DLL( ReloadScript )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	if ( szData )
	{
		CSquirrel* pScript = CSquirrelManager::Find( szData );
		if ( pScript )
		{
			CSquirrelManager::Remove( pScript );

			FILE* pFile = fopen( szData, "r" );

			if ( pFile ) 
			{
				pScript = CSquirrelManager::New( szData );

				fclose( pFile );

				strcpy( data, "1" );
				return 3;
			}
		}
	}

	return 3;
}

_MIRC_DLL( UnloadScript )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	if ( szData )
	{
		CSquirrel* pScript = CSquirrelManager::Find( szData );
		if ( pScript )
		{
			CSquirrelManager::Remove( pScript );

			strcpy( data, "1" );
			return 3;
		}
	}

	return 3;
}

_MIRC_DLL( OnInput )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	unsigned char ucTokens = CUtils::NumTok( szData, " " );
	if ( ( szData ) && ( ucTokens >= 2 ) )
	{
		char szNick[ 64 ] = { NULL };
		strcpy( szNick, strtok( szData, " " ) );
		if ( strlen( szNick ) > 0 )
		{
			char szText[ 512 ] = { NULL };
			strcpy( szText, strtok( 0, "\n" ) );
			if ( strlen( szText ) > 0 )
			{
				CScripting::PushFunction( "OnInput" );
				CScripting::PushString( szNick );
				CScripting::PushString( szText );
				CScripting::CallFunction();
			}
		}
	}

	return 1;
}

_MIRC_DLL( OnText )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	unsigned char ucTokens = CUtils::NumTok( szData, " " );
	if ( ( szData ) && ( ucTokens >= 3 ) )
	{
		char szNick[ 64 ] = { NULL };
		strcpy( szNick, strtok( szData, " " ) );
		if ( strlen( szNick ) > 0 )
		{
			char szChannel[ 64 ] = { NULL };
			strcpy( szChannel, strtok( 0, " " ) );
			if ( strlen( szChannel ) > 0 )
			{
				char szText[ 512 ] = { NULL };
				strcpy( szText, strtok( 0, "\n" ) );
				if ( strlen( szText ) > 0 )
				{
					CScripting::PushFunction( "OnText" );
					CScripting::PushString( szNick );
					CScripting::PushString( szChannel );
					CScripting::PushString( szText );
					CScripting::CallFunction();
				}
			}
		}
	}

	return 1;
}

_MIRC_DLL( OnAction )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	unsigned char ucTokens = CUtils::NumTok( szData, " " );
	if ( ( szData ) && ( ucTokens >= 3 ) )
	{
		char szNick[ 64 ] = { NULL };
		strcpy( szNick, strtok( szData, " " ) );
		if ( strlen( szNick ) > 0 )
		{
			char szChannel[ 64 ] = { NULL };
			strcpy( szChannel, strtok( 0, " " ) );
			if ( strlen( szChannel ) > 0 )
			{
				char szText[ 512 ] = { NULL };
				strcpy( szText, strtok( 0, "\n" ) );
				if ( strlen( szText ) > 0 )
				{
					CScripting::PushFunction( "OnAction" );
					CScripting::PushString( szNick );
					CScripting::PushString( szChannel );
					CScripting::PushString( szText );
					CScripting::CallFunction();
				}
			}
		}
	}

	return 1;
}

_MIRC_DLL( OnNotice )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	unsigned char ucTokens = CUtils::NumTok( szData, " " );
	if ( ( szData ) && ( ucTokens >= 3 ) )
	{
		char szNick[ 64 ] = { NULL };
		strcpy( szNick, strtok( szData, " " ) );
		if ( strlen( szNick ) > 0 )
		{
			char szChannel[ 64 ] = { NULL };
			strcpy( szChannel, strtok( 0, " " ) );
			if ( strlen( szChannel ) > 0 )
			{
				char szText[ 512 ] = { NULL };
				strcpy( szText, strtok( 0, "\n" ) );
				if ( strlen( szText ) > 0 )
				{
					CScripting::PushFunction( "OnNotice" );
					CScripting::PushString( szNick );
					CScripting::PushString( szChannel );
					CScripting::PushString( szText );
					CScripting::CallFunction();
				}
			}
		}
	}

	return 1;
}

_MIRC_DLL( CallSquirrel )
{
	char szData [ 900 ] = { 0 };
	strcpy ( szData, data );
	strcpy ( data, "0" );

	unsigned char ucTokens = CUtils::NumTok( szData, " " );
	if ( ( szData ) && ( ucTokens >= 1 ) )
	{
		char szFunc[ 64 ] = { NULL };
		char szTemp[ 256 ] = { NULL };
		strcpy( szFunc, strtok( szData, " " ) );
		if ( strlen( szFunc ) > 0 )
		{
			CScripting::PushFunction( szFunc );
			for ( unsigned char uc = 1; uc < ucTokens; uc++ )
			{
				strcpy( szTemp, strtok( 0, " " ) );
				if ( CUtils::IsNum( szTemp ) ) CScripting::PushInteger( atoi( szTemp ) );
				else CScripting::PushString( szTemp );
			}
			CScripting::CallFunction();
		}
	}

	return 1;
}

//--------------------------------------------------------------------------------//

typedef struct
{
	DWORD  mVersion;
	HWND   mHwnd;
	BOOL   mKeep;
} LOADINFO;

void WINAPI LoadDll ( LOADINFO *li )
{
	_mWnd = li->mHwnd;

	hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,4096,"mIRC");	
	mData = (LPSTR)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
}

int WINAPI UnloadDll ( int timeout )
{
	if ( ( !timeout ) || ( timeout == 2 ) )
	{
		// Do your stuff that executes on DLL Unload
		CSquirrelManager::RemoveAll();

		if ( mData ) UnmapViewOfFile(mData);
		if ( hFileMap ) CloseHandle(hFileMap);

		return 1;
	}
	return 0;
}

void CallSignal ( char* szAlias, char* szParams, ... )
{
	if ( szParams )
	{
		char sz [ 500 ] = { 0 };
		va_list va_alist;
		va_start( va_alist, szParams );
		_vsnprintf( sz, sizeof ( sz ), szParams, va_alist );
		va_end( va_alist );

		wsprintf ( mData, "/.signal %s %s", szAlias, sz );
	}
	else wsprintf ( mData, "/.signal %s %s", szAlias, szParams );
	SendMessage ( _mWnd, WM_USER + 200, 0, 0 );
}

void CallAlias ( char* szAlias, char* szParams, ... )
{
	if ( szParams )
	{
		char sz [ 500 ] = { 0 };
		va_list va_alist;
		va_start( va_alist, szParams );
		_vsnprintf( sz, sizeof ( sz ), szParams, va_alist );
		va_end( va_alist );

		wsprintf ( mData, "$%s(%s)", szAlias, sz );
	}
	else wsprintf ( mData, "$%s(%s)", szAlias, szParams );
	SendMessage ( _mWnd, WM_USER + 201, 0, 0 );
}

void CallFunc( char* szAlias, char* szParams, ... )
{
	if ( szParams )
	{
		char sz [ 500 ] = { 0 };
		va_list va_alist;
		va_start( va_alist, szParams );
		_vsnprintf( sz, sizeof ( sz ), szParams, va_alist );
		va_end( va_alist );

		strcpy( sz, strtok( sz, "\n" ) );

		wsprintf ( mData, "/%s %s", szAlias, sz );
	}
	else wsprintf ( mData, "/%s %s", szAlias, szParams );
	SendMessage ( _mWnd, WM_USER + 200, 1, 0 );
}